﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using CygwinPackageManager.Common;
using CygwinPackageManager.Properties;

namespace CygwinPackageManager
{
	[Docking(DockingBehavior.Ask)]
	[DefaultEvent("SelectionChanged")]
	public partial class PackageGrid : UserControl
	{
		#region UserControl LifeCycle
		public PackageGrid()
		{
			InitializeComponent();
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			UpdateDataView();
		}
		#endregion

		#region Private Methods
		private void UpdateDataView()
		{
			if (ShowMenu)
			{
				BuildContextMenu();
			}
		}

		private void BuildContextMenu()
		{
			Dictionary<string, List<ToolStripMenuItem>> menuItemGroups = new Dictionary<string, List<ToolStripMenuItem>>();
			foreach (PackageAction action in (new PackageActionDALC()).GetStatuses())
			{
				ToolStripMenuItem actionItem = new ToolStripMenuItem();
				actionItem.Text = action.Name;
				actionItem.ToolTipText = action.Description;
				actionItem.Tag = action.PackageActionID;

				Image image = null;
				switch ((PackageActionIndex)action.PackageActionID)
				{
					case PackageActionIndex.DependenciesInstall:
					case PackageActionIndex.Install:
						image = Resources.package_install;
						break;
					case PackageActionIndex.DependenciesRemove:
					case PackageActionIndex.Remove:
						image = Resources.package_remove;
						break;
					case PackageActionIndex.DependenciesUpdate:
					case PackageActionIndex.Update:
						image = Resources.package_upgrade;
						break;
				}
				if (image != null)
					actionItem.Image = image;

				actionItem.Click += new EventHandler(actionItem_Click);

				string groupName = action.Group;
				if (!menuItemGroups.ContainsKey(groupName))
					menuItemGroups.Add(groupName, new List<ToolStripMenuItem>());

				menuItemGroups[groupName].Add(actionItem);
			}

			bool firstGroup = true;
			foreach (List<ToolStripMenuItem> menuItemGroup in menuItemGroups.Values)
			{
				if (!firstGroup)
				{
					contextMenuStrip1.Items.Add(new ToolStripSeparator());
				}
				else
				{
					firstGroup = false;
				}

				foreach (ToolStripMenuItem menuItem in menuItemGroup)
				{
					contextMenuStrip1.Items.Add(menuItem);
				}
			}
		}
		#endregion

		#region Properties
		public bool ShowMenu { get; set; }
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public SearchableSortableBindingList<PackageInfo> Packages
		{
			get { return packageInfoBindingSource.DataSource as SearchableSortableBindingList<PackageInfo>; }
			set { packageInfoBindingSource.DataSource = value; }
		}

		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public IEnumerable<int> SelectedPackageIDs
		{
			get
			{
				return from row in dataGridView1.SelectedRows.Cast<DataGridViewRow>()
					   select (row.DataBoundItem as PackageInfo).PackageID;
			}
		}
		#endregion

		#region Events
		public event EventHandler<PackageActionEventArgs> Action;
		protected virtual void OnAction(PackageActionEventArgs e)
		{
			if (Action != null)
				Action(this, e);
		}

		public event EventHandler SelectionChanged;
		protected virtual void OnSelectionChanged(EventArgs e)
		{
			if (SelectionChanged != null)
				SelectionChanged(this, e);
		}
		#endregion

		#region Miscelaneous
		enum GridColumnIndex
		{
			Status = 1
		}
		#endregion

		#region Event Handlers
		void actionItem_Click(object sender, EventArgs e)
		{
			ToolStripMenuItem actionItem = sender as ToolStripMenuItem;
			PackageActionEventArgs args = new PackageActionEventArgs()
			{
				PackageActionID = (int)actionItem.Tag
			};
			OnAction(args);
		}

		private void dataGridView1_SelectionChanged(object sender, EventArgs e)
		{
			OnSelectionChanged(e);
		}

		private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
		{
			switch ((GridColumnIndex)e.ColumnIndex)
			{
				case GridColumnIndex.Status:
					{
						if (e.Value is Image)
							return;
						PackageStatusIndex status = (PackageStatusIndex)e.Value;
						Image image = null;
						switch (status)
						{
							case PackageStatusIndex.Available: image = Resources.package_available; break;
							case PackageStatusIndex.InstalledOutdated: image = Resources.package_installed_outdated; break;
							case PackageStatusIndex.InstalledUpdated: image = Resources.package_installed_updated; break;
							case PackageStatusIndex.MarkedForInstallation: image = Resources.package_install; break;
							case PackageStatusIndex.MarkedForRemoval: image = Resources.package_remove; break;
							case PackageStatusIndex.MarkedForUpdate: image = Resources.package_upgrade; break;
							default: throw new NotImplementedException();
						}

						e.Value = image;
						e.FormattingApplied = true;
					}
					break;
			}
		}

		private void dataGridView1_RowContextMenuStripNeeded(object sender, DataGridViewRowContextMenuStripNeededEventArgs e)
		{
			if (ShowMenu)
				e.ContextMenuStrip = contextMenuStrip1;
		}

		#endregion
	}
}
